import { ICacheService } from './interfaces/ICacheService';
import { CacheEntry } from '../types/index';

export class CacheService implements ICacheService {
  private readonly CACHE_PREFIX = 'eko_cache_';
  private readonly CACHE_INDEX_KEY = 'eko_cache_index';

  async set<T>(key: string, data: T, expiryMs: number): Promise<void> {
    const now = Date.now();
    const entry: CacheEntry<T> = {
      data,
      timestamp: now,
      expiry: now + expiryMs,
      version: '1.0.0'
    };

    const cacheKey = this.getCacheKey(key);
    
    try {
      // 存储缓存条目
      await new Promise<void>((resolve, reject) => {
        chrome.storage.local.set({ [cacheKey]: entry }, () => {
          if (chrome.runtime.lastError) {
            reject(new Error(chrome.runtime.lastError.message));
          } else {
            resolve();
          }
        });
      });

      // 更新缓存索引
      await this.updateCacheIndex(key, now + expiryMs);
    } catch (error) {
      console.error('缓存设置失败:', error);
      throw new Error(`缓存设置失败: ${error instanceof Error ? error.message : '未知错误'}`);
    }
  }

  async get<T>(key: string): Promise<T | null> {
    const cacheKey = this.getCacheKey(key);
    
    try {
      const result = await new Promise<{ [key: string]: CacheEntry<T> }>((resolve) => {
        chrome.storage.local.get([cacheKey], resolve);
      });

      const entry = result[cacheKey];
      if (!entry) {
        return null;
      }

      // 检查是否过期
      if (Date.now() > entry.expiry) {
        // 异步删除过期缓存
        this.delete(key).catch(console.error);
        return null;
      }

      return entry.data;
    } catch (error) {
      console.error('缓存获取失败:', error);
      return null;
    }
  }

  async has(key: string): Promise<boolean> {
    const data = await this.get(key);
    return data !== null;
  }

  async delete(key: string): Promise<void> {
    const cacheKey = this.getCacheKey(key);
    
    try {
      await new Promise<void>((resolve, reject) => {
        chrome.storage.local.remove([cacheKey], () => {
          if (chrome.runtime.lastError) {
            reject(new Error(chrome.runtime.lastError.message));
          } else {
            resolve();
          }
        });
      });

      // 从索引中移除
      await this.removeFromCacheIndex(key);
    } catch (error) {
      console.error('缓存删除失败:', error);
      throw new Error(`缓存删除失败: ${error instanceof Error ? error.message : '未知错误'}`);
    }
  }

  async clear(): Promise<void> {
    try {
      // 获取所有缓存键
      const index = await this.getCacheIndex();
      const cacheKeys = Object.keys(index).map(key => this.getCacheKey(key));
      
      if (cacheKeys.length === 0) {
        return;
      }

      // 删除所有缓存条目
      await new Promise<void>((resolve, reject) => {
        chrome.storage.local.remove([...cacheKeys, this.CACHE_INDEX_KEY], () => {
          if (chrome.runtime.lastError) {
            reject(new Error(chrome.runtime.lastError.message));
          } else {
            resolve();
          }
        });
      });
    } catch (error) {
      console.error('清除缓存失败:', error);
      throw new Error(`清除缓存失败: ${error instanceof Error ? error.message : '未知错误'}`);
    }
  }

  async clearExpired(): Promise<void> {
    try {
      const index = await this.getCacheIndex();
      const now = Date.now();
      const expiredKeys: string[] = [];

      // 找出过期的键
      Object.entries(index).forEach(([key, expiry]) => {
        if (now > expiry) {
          expiredKeys.push(key);
        }
      });

      if (expiredKeys.length === 0) {
        return;
      }

      // 删除过期的缓存条目
      const cacheKeys = expiredKeys.map(key => this.getCacheKey(key));
      await new Promise<void>((resolve, reject) => {
        chrome.storage.local.remove(cacheKeys, () => {
          if (chrome.runtime.lastError) {
            reject(new Error(chrome.runtime.lastError.message));
          } else {
            resolve();
          }
        });
      });

      // 更新索引
      const newIndex = { ...index };
      expiredKeys.forEach(key => {
        delete newIndex[key];
      });

      await new Promise<void>((resolve, reject) => {
        chrome.storage.local.set({ [this.CACHE_INDEX_KEY]: newIndex }, () => {
          if (chrome.runtime.lastError) {
            reject(new Error(chrome.runtime.lastError.message));
          } else {
            resolve();
          }
        });
      });
    } catch (error) {
      console.error('清除过期缓存失败:', error);
      throw new Error(`清除过期缓存失败: ${error instanceof Error ? error.message : '未知错误'}`);
    }
  }

  /**
   * 获取缓存统计信息
   */
  async getCacheStats(): Promise<{
    totalEntries: number;
    expiredEntries: number;
    totalSize: number;
  }> {
    try {
      const index = await this.getCacheIndex();
      const now = Date.now();
      let expiredCount = 0;

      Object.values(index).forEach(expiry => {
        if (now > expiry) {
          expiredCount++;
        }
      });

      // 获取存储使用情况
      const bytesUsed = await new Promise<number>((resolve) => {
        chrome.storage.local.getBytesInUse((bytes) => {
          resolve(bytes || 0);
        });
      });

      return {
        totalEntries: Object.keys(index).length,
        expiredEntries: expiredCount,
        totalSize: bytesUsed
      };
    } catch (error) {
      console.error('获取缓存统计失败:', error);
      return {
        totalEntries: 0,
        expiredEntries: 0,
        totalSize: 0
      };
    }
  }

  /**
   * 获取所有缓存键
   */
  async getAllCacheKeys(): Promise<string[]> {
    const index = await this.getCacheIndex();
    return Object.keys(index);
  }

  private getCacheKey(key: string): string {
    return `${this.CACHE_PREFIX}${key}`;
  }

  private async getCacheIndex(): Promise<{ [key: string]: number }> {
    try {
      const result = await new Promise<{ [key: string]: { [key: string]: number } }>((resolve) => {
        chrome.storage.local.get([this.CACHE_INDEX_KEY], resolve);
      });

      return result[this.CACHE_INDEX_KEY] || {};
    } catch (error) {
      console.error('获取缓存索引失败:', error);
      return {};
    }
  }

  private async updateCacheIndex(key: string, expiry: number): Promise<void> {
    try {
      const index = await this.getCacheIndex();
      index[key] = expiry;

      await new Promise<void>((resolve, reject) => {
        chrome.storage.local.set({ [this.CACHE_INDEX_KEY]: index }, () => {
          if (chrome.runtime.lastError) {
            reject(new Error(chrome.runtime.lastError.message));
          } else {
            resolve();
          }
        });
      });
    } catch (error) {
      console.error('更新缓存索引失败:', error);
    }
  }

  private async removeFromCacheIndex(key: string): Promise<void> {
    try {
      const index = await this.getCacheIndex();
      delete index[key];

      await new Promise<void>((resolve, reject) => {
        chrome.storage.local.set({ [this.CACHE_INDEX_KEY]: index }, () => {
          if (chrome.runtime.lastError) {
            reject(new Error(chrome.runtime.lastError.message));
          } else {
            resolve();
          }
        });
      });
    } catch (error) {
      console.error('从缓存索引移除失败:', error);
    }
  }
}